
/*
 * @Author: c
 * @Date: 2024-01-08 22:21:09
 * @LastEditTime: 2024-04-01 04:25:59
 * @LastEditors: c
 * @Description: 
 * @FilePath: \music-web-backend\src\core\music\video\video.service.ts
 * https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
import { Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { plainToClass } from 'class-transformer';
import * as dayjs from 'dayjs';
import { EXCEPTION } from 'src/common/const/constants';
import { PageResDto } from 'src/common/dto/page.dto';
import { CommonException } from 'src/common/exception/common.exception';
import { MinioClientService } from 'src/core/system/minio/minio.service';
import { User } from 'src/core/system/user/entities/user.entity';
import { DataSource, Repository } from 'typeorm';
import { Artist } from '../artist/entities/artist.entity';
import { Category } from '../category/entities/category.entity';
import { SongDto } from '../song/dto/search-song.dto';
import { SongService } from '../song/song.service';
import { DVideo } from './dao/video.dao';
import { VideoForm } from './dto/create-video.dto';
import { VideoPageQuery, VideoVo } from './dto/search-video.dto';
import { Video } from './entities/video.entity';

@Injectable()
export class VideoService {

  constructor(
    @InjectRepository(Video) private videoRepository: Repository<Video>,
    private dataSource: DataSource,
    private minioClientService: MinioClientService,
    private songService: SongService,
    private dvideo: DVideo,
  ) { }

  /**
   * 视频-单个-新增
   * @param videoForm 
   * @returns 
   */
  async saveVideo(req: any, videoForm: VideoForm) {

    let video = plainToClass(Video, videoForm)
    let song: SongDto = null;
    if (videoForm.songIds.length) {
      song = await this.songService.findOne(req, videoForm.songIds.at(0))
      video.title = song.title
      video.introduce = song.introduce
      video.lang = song.lang
      videoForm.artistIds = song.artistList.map(artist => artist.id)
      videoForm.genre = song.genre as number
    }

    const queryRunner = this.dataSource.createQueryRunner();
    await queryRunner.connect()

    await queryRunner.startTransaction()
    try {

      //插入video表
      const { generatedMaps, identifiers } = await queryRunner.manager
        .createQueryBuilder()
        .insert()
        .into(Video)
        .values(video)
        .execute()

      const videoId = identifiers.at(0).id

      //插入artist_video表的数据
      await queryRunner.manager
        .createQueryBuilder()
        .relation(Video, 'song')
        .of(videoId)
        // .insert(videoForm.artistIds)
        .set(videoForm.songIds.at(0))//多对多关系 新增与歌手的关系

      //插入artist_video表的数据
      await queryRunner.manager
        .createQueryBuilder()
        .relation(Video, 'artistList')
        .of(videoId)
        // .insert(videoForm.artistIds)
        .add(videoForm.artistIds)//多对多关系 新增与歌手的关系


      //插入video_cate表的数据
      await queryRunner.manager
        .createQueryBuilder()
        .relation(Video, 'genre')
        .of(videoId)
        .add(videoForm.genre)//多对多关系 新增与歌手的关系


      await queryRunner.commitTransaction()

    } catch (error) {
      Logger.error(error)
      await queryRunner.rollbackTransaction()
      throw new CommonException(EXCEPTION.COMMON)
    } finally {
      await queryRunner.release()
    }

    let date = plainToClass(Video, videoForm)
    // return this.videoRepository.save()



    return date
  }

  /**
 * 视频-分页-查询
 * @param param0 
 * @returns 
 */
  async page(user: User, { name, pageNum, pageSize }: VideoPageQuery) {

    const [data, total] = await this.dvideo.page(user?.username, name, pageNum, pageSize)

    return PageResDto.result(data, total)
  }
  /**
 * 视频-推荐列表-查询
 * @param param0 
 * @returns 
 */
  async getRecommendVideo(user: User, pageNum: number = 1, pageSize: number = 10) {

    const [data, total] = await this.dvideo.getRecommnedList(user?.username, pageNum, pageSize)

    return PageResDto.result(data, total)
  }


  /**
   * 视频-下拉选项
   * @param videoName 
   * @param artistIds 
   */
  listVideoOptions(videoName: any, artistIds: number[]) {
    throw new Error('Method not implemented.');
  }

  /**
   * 视频-删除
   * @param ids 
   */
  removeByIds(ids: number[]) {
    this.videoRepository.softDelete(ids)
  }

  /**
   * 视频-获取单条数据
   * @param req 
   * @param id 
   */
  async getVideoFormData(user: User, id: any) {
   
    const video: Video = await this.dvideo.findOne(user?.username, id)
    const videoVo: VideoVo = plainToClass(VideoVo, video);
    videoVo.songOptions = video.song ? [{ label: video.song.title, value: video.song.id }] : []
    videoVo.songIds = video.song ? [video.song.id] : []
    videoVo.url = (await this.minioClientService.presignedGetObject('private', video.objectName)).url
    videoVo.originalReleaseDate = dayjs(video.originalReleaseDate).format("YYYY-MM-DD") 
    videoVo.genre = video.genre.at(0).id
    return videoVo
  }


  /**
     * 视频-修改
     * @param videoId 
     * @param videoForm 
     * @returns 
     */
  async update(videoId: number, videoForm: VideoForm) {

    let data = plainToClass(Video, videoForm)
    const artists = videoForm.artistIds.map(id => new Artist({ id }))

    //修改类别
    const cate = new Category(+videoForm.genre)

    //分类
    data.genre = [cate]

    //歌手
    data.artistList = artists

    return this.videoRepository.save(data);
  }





}
